package com.cardbaobao.cardbabyclient.widget.banner;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Handler;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Scroller;

import com.cardbaobao.cardbabyclient.R;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Jiangzx on 13:41.
 */

public class BannerView<T> extends RelativeLayout {
    private ViewGroup parent;
    private ViewPager mViewPager;
    private BannerPagerAdapter mAdapter;
    private List<T> mData;
    private boolean mIsAutoPlay = true;// 是否自动播放
    private int mCurrentItem = 0;//当前位置
    private Handler mHandler = new Handler();
    private int mDelayedTime = 3000;// Banner 切换时间间隔
    private ViewPagerScroller mViewPagerScroller;//控制ViewPager滑动速度的Scroller
    private boolean mIsOpenEffect = true;// 开启魅族Banner效果
    private boolean mIsCanLoop = true;// 是否轮播图片
    private LinearLayout mIndicatorContainer;//indicator容器
    private ArrayList<ImageView> mIndicators = new ArrayList<>();
    private int mIndicatorPaddingLeft = 0;
    private int mIndicatorPaddingRight = 0;
    private int mTransformerPadding = 0;//由于前后显示了上下一个页面的部分，因此需要计算这部分padding
    private int mIndicatorAlign = 1;
    private int mIndicatorColorNormal=0xff000000;//指示器正常时的颜色
    private int mIndicatorColorSelected=0xffeeeeee;//指示器选中时的颜色
    private int mIndicatorSizeNormal=30;//指示器正常时大小
    private int mIndicatorSizeSelected=30;//指示器选中时大小
    private Drawable mIndicatorDrawableNormal;
    private Drawable mIndicatorDrawableSelected;
    private ViewPager.OnPageChangeListener mOnPageChangeListener;
    private enum IndicatorAlign{
        LEFT,//做对齐
        CENTER,//居中对齐
        RIGHT //右对齐
    }
    public BannerView(Context context) {
        super(context);
        init();
    }

    public BannerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        readAttrs(context,attrs);
        init();
    }

    public BannerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        readAttrs(context,attrs);
        init();
    }

    private void readAttrs(Context context,AttributeSet attrs){
        TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.BannerView);
        mIsOpenEffect = typedArray.getBoolean(R.styleable.BannerView_open_transformer,true);
        mIsCanLoop = typedArray.getBoolean(R.styleable.BannerView_canLoop,true);
        mIndicatorAlign = typedArray.getInt(R.styleable.BannerView_indicatorAlign,1);
        mIndicatorPaddingLeft = typedArray.getDimensionPixelSize(R.styleable.BannerView_indicatorPaddingLeft,0);
        mIndicatorPaddingRight = typedArray.getDimensionPixelSize(R.styleable.BannerView_indicatorPaddingRight,0);
        mIndicatorColorNormal=typedArray.getColor(R.styleable.BannerView_indicatorColorNormal,mIndicatorColorNormal);
        mIndicatorColorSelected=typedArray.getColor(R.styleable.BannerView_indicatorColorSelected,mIndicatorColorSelected);
        mIndicatorSizeNormal=typedArray.getDimensionPixelSize(R.styleable.BannerView_indicatorSizeNormal,
                mIndicatorSizeNormal);
        mIndicatorSizeSelected=typedArray.getDimensionPixelSize(R.styleable.BannerView_indicatorSizeSelected,
                mIndicatorSizeSelected);
        typedArray.recycle();
    }

    private void init(){
        View view;
        if(mIsOpenEffect){
            view = LayoutInflater.from(getContext()).inflate(R.layout.wigdet_banner_effect_layout,this,true);
        }else{
            view = LayoutInflater.from(getContext()).inflate(R.layout.wigdet_banner_normal_layout,this,true);
        }
        mIndicatorContainer = (LinearLayout) view.findViewById(R.id.banner_indicator_container);
        mViewPager = (ViewPager) view.findViewById(R.id.banner_vp);
        mViewPager.setOffscreenPageLimit(3);

        mTransformerPadding = dpToPx(30);

        mIndicatorDrawableNormal =new GradientDrawable(GradientDrawable.Orientation.TL_BR,
                new int[]{mIndicatorColorNormal,mIndicatorColorNormal});
        mIndicatorDrawableNormal.setBounds(0,0,mIndicatorSizeNormal,mIndicatorSizeNormal);
        mIndicatorDrawableSelected=new GradientDrawable(GradientDrawable.Orientation.TL_BR,
                new int[]{mIndicatorColorSelected,mIndicatorColorSelected});
        mIndicatorDrawableSelected.setBounds(0,0,mIndicatorSizeSelected,mIndicatorSizeSelected);

        // 初始化Scroller
        initViewPagerScroll();

        if(mIndicatorAlign == 0){
            setIndicatorAlign(IndicatorAlign.LEFT);
        }else if(mIndicatorAlign == 1){
            setIndicatorAlign(IndicatorAlign.CENTER);
        }else{
            setIndicatorAlign(IndicatorAlign.RIGHT);
        }
        setClipChildren(false);
    }

    /**
     * 设置滑动事件与下拉刷新事件冲突的ViewGroup
     */
    public void setParent(ViewGroup parentRefreshLayout){
        this.parent=parentRefreshLayout;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        int action=ev.getAction();
        switch (action){
            case MotionEvent.ACTION_DOWN:
                if(parent!=null){
                    parent.requestDisallowInterceptTouchEvent(true);
                }
                break;
            case MotionEvent.ACTION_CANCEL:
                if(parent!=null){
                    parent.requestDisallowInterceptTouchEvent(false);
                }
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    /**
     * 设置ViewPager的滑动速度
     * */
    private void initViewPagerScroll() {
        try {
            Field mScroller;
            mScroller = ViewPager.class.getDeclaredField("mScroller");
            mScroller.setAccessible(true);
            mViewPagerScroller = new ViewPagerScroller(
                    mViewPager.getContext());
            mScroller.set(mViewPager, mViewPagerScroller);
        } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }


    private final Runnable mLoopRunnable = new Runnable() {
        @Override
        public void run() {
            if(mIsAutoPlay){
                mCurrentItem = mViewPager.getCurrentItem();
                mCurrentItem++;

                if(mCurrentItem == mAdapter.getCount() - 1){
                    mCurrentItem = 0;
                    mViewPager.setCurrentItem(mCurrentItem,false);
                    mHandler.postDelayed(this,mDelayedTime);
                }else{
                    if(mCurrentItem<0){
                        mCurrentItem=0;//int类型溢出时，重置为0
                    }
                    mViewPager.setCurrentItem(mCurrentItem);
                    mHandler.postDelayed(this,mDelayedTime);
                }
            }else{
                mHandler.postDelayed(this,mDelayedTime);
            }
        }
    };

    /**
     * 初始化指示器Indicator
     */
    private void initIndicator(){
        mIndicatorContainer.removeAllViews();
        mIndicators.clear();
            for(int i = 0; i< mData.size(); i++){
                ImageView imageView = new ImageView(getContext());
                if(mIndicatorAlign == IndicatorAlign.LEFT.ordinal()){
                    if(i == 0){
                        int paddingLeft = mIsOpenEffect ? mIndicatorPaddingLeft+ mTransformerPadding :mIndicatorPaddingLeft;
                        imageView.setPadding(paddingLeft+6,0,6,0);
                    } else{
                        imageView.setPadding(6,0,6,0);
                    }
                }else if(mIndicatorAlign == IndicatorAlign.RIGHT.ordinal()){
                    if(i == mData.size() - 1){
                        int paddingRight = mIsOpenEffect ? mTransformerPadding + mIndicatorPaddingRight:mIndicatorPaddingRight;
                        imageView.setPadding(6,0,6 + paddingRight,0);
                    }else{
                        imageView.setPadding(6,0,6,0);
                    }

                }else{
                    imageView.setPadding(6,0,6,0);
                }
                if(i == (mCurrentItem % mData.size())){
                    imageView.setImageDrawable(mIndicatorDrawableSelected);
                }else{
                    imageView.setImageDrawable(mIndicatorDrawableNormal);
                }

                mIndicators.add(imageView);
                mIndicatorContainer.addView(imageView);
            }
    }

    /******************************************************************************************************/
    /**                             对外API                                                               **/
    /******************************************************************************************************/
    /**
     * 开始轮播
     * <p>应该确保在调用用了{@link BannerView {@link #setPages(List, BannerHolderCreator,android.support.v4.view.ViewPager.PageTransformer)}} 之后调用这个方法开始轮播</p>
     */
    public void start(){
        // 如果Adapter为null, 说明还没有设置数据，这个时候不应该轮播Banner
        if(mAdapter== null){
            return;
        }
        if(mIsCanLoop){
            mIsAutoPlay = true;
            mHandler.postDelayed(mLoopRunnable,mDelayedTime);
        }
    }

    /**
     * 停止轮播
     */
    public void pause(){
        mIsAutoPlay = false;
        mHandler.removeCallbacks(mLoopRunnable);
    }

    /**
     * 设置BannerView 的切换时间间隔
     */
    public void setDelayedTime(int delayedTime) {
        mDelayedTime = delayedTime;
    }

    /**
     * 是否显示Indicator
     * @param visible true 显示Indicator，否则不显示
     */
    public void setIndicatorVisible(boolean visible){
        if(visible){
            mIndicatorContainer.setVisibility(VISIBLE);
        }else{
            mIndicatorContainer.setVisibility(GONE);
        }
    }

    /**
     * 返回ViewPager
     * @return {@link ViewPager}
     */
    public ViewPager getViewPager() {
        return mViewPager;
    }

    /**
     * 设置数据，这是最重要的一个方法。
     * <p>其他的配置应该在这个方法之前调用</p>
     * @param data Banner 展示的数据集合
     * @param holderCreator  ViewHolder生成器 {@link BannerHolderCreator} And {@link BannerViewHolder}
     */
    public void setPages(List<T> data,BannerHolderCreator holderCreator,ViewPager.PageTransformer transformer){
        if(data == null ||data.size()==0|| holderCreator == null){
            return;
        }
        mData = data;
        if(mIsOpenEffect&&transformer!=null){
            mViewPager.setPageTransformer(false,transformer);
        }

        mAdapter = new BannerPagerAdapter(data,holderCreator,mIsCanLoop);
        mAdapter.setUpViewViewPager(mViewPager);
        mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                mCurrentItem = position;
                    // 切换indicator
                    int realSelectPosition = mCurrentItem % mIndicators.size();
                    for(int i = 0; i< mData.size(); i++){
                        if(i == realSelectPosition){
                            mIndicators.get(i).setImageDrawable(mIndicatorDrawableSelected);
                        }else{
                            mIndicators.get(i).setImageDrawable(mIndicatorDrawableNormal);
                        }
                    }
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                switch (state){
                    case ViewPager.SCROLL_STATE_DRAGGING:
                        mIsAutoPlay = false;
                        break;
                    case ViewPager.SCROLL_STATE_SETTLING:
                        mIsAutoPlay = true;
                        break;

                }
            }
        });
        if(mOnPageChangeListener!=null){
            mViewPager.addOnPageChangeListener(mOnPageChangeListener);
        }
        //初始化Indicator
        initIndicator();
    }

    /**
     * 设置Indicator 的对齐方式
     * @param indicatorAlign {@link IndicatorAlign#CENTER }{@link IndicatorAlign#LEFT }{@link IndicatorAlign#RIGHT }
     */
    public void setIndicatorAlign(IndicatorAlign indicatorAlign) {
        mIndicatorAlign = indicatorAlign.ordinal();
        LayoutParams layoutParams = (LayoutParams) mIndicatorContainer.getLayoutParams();
        if(indicatorAlign == IndicatorAlign.LEFT){
            layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
        }else if(indicatorAlign == IndicatorAlign.RIGHT){
            layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
        }else{
            layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
        }
        mIndicatorContainer.setLayoutParams(layoutParams);
    }

    /**
     * 设置ViewPager切换的速度
     */
    public void setDuration(int duration){
        mViewPagerScroller.setDuration(duration);
    }

    /**
     * 获取Banner页面切换动画时间
     */
    public int getDuration(){
        return mViewPagerScroller.getScrollDuration();
    }

    public static class  BannerPagerAdapter<T> extends PagerAdapter {
        private List<T> mData;
        private BannerHolderCreator mHolderCreator;
        private ViewPager mViewPager;
        private boolean canLoop;
        private final int mLooperCountFactor = 500;

        public BannerPagerAdapter(List<T> data, BannerHolderCreator holderCreator,boolean canLoop) {
            if(mData == null){
                mData = new ArrayList<>();
            }
            for(T t:data){
                mData.add(t);
            }
            mHolderCreator = holderCreator;
            this.canLoop = canLoop;
        }

        /**
         * 初始化Adapter和设置当前选中的Item
         */
        public void setUpViewViewPager(ViewPager viewPager){
            mViewPager = viewPager;
            mViewPager.setAdapter(this);
            mViewPager.getAdapter().notifyDataSetChanged();
            int currentItem = canLoop ? getStartSelectItem():0;
            //设置当前选中的Item
            mViewPager.setCurrentItem(currentItem);
        }

        private int getStartSelectItem(){
            // 我们设置当前选中的位置为Integer.MAX_VALUE / 2,这样开始就能往左滑动
            // 但是要保证这个值与getRealPosition 的 余数为0，因为要从第一页开始显示
            int currentItem = getRealCount() * mLooperCountFactor / 2;
            if(currentItem % getRealCount()  ==0 ){
                return currentItem;
            }
            // 直到找到从0开始的位置
            while (currentItem % getRealCount() != 0){
                currentItem++;
            }
            return currentItem;
        }

        public void setDatas(List<T> data) {
            mData = data;
        }

        @Override
        public int getCount() {
            // 2017.6.10 bug fix
            // 如果getCount 的返回值为Integer.MAX_VALUE 的话，那么在setCurrentItem的时候会ANR(除了在onCreate 调用之外)
            return canLoop ? getRealCount() * mLooperCountFactor : getRealCount();//ViewPager返回int 最大值
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, final int position) {
            View view = getView(position,container);
            container.addView(view);
            return view;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }

        @Override
        public void finishUpdate(ViewGroup container) {
            // 轮播模式才执行
            if(canLoop){
                int position = mViewPager.getCurrentItem();
                if (position == getCount() - 1) {
                    position = 0;
                    setCurrentItem(position);
                }
            }

        }

        private void setCurrentItem(int position){
            try {
                mViewPager.setCurrentItem(position, false);
            }catch (IllegalStateException e){
                e.printStackTrace();
            }
        }

        /**
         * 获取真实的Count
         */
        private int getRealCount(){
            return  mData==null ? 0:mData.size();
        }

        private View getView(int position,ViewGroup container){

            final int realPosition = position % getRealCount();
            BannerViewHolder holder =null;
            // create holder
            holder = mHolderCreator.createViewHolder();

            if(holder == null){
                throw new RuntimeException("can not return a null holder");
            }
            // create View
            View view = holder.createView(container.getContext());
            if( mData!=null && mData.size()>0){
                holder.onBind(container.getContext(),realPosition,mData.get(realPosition));
            }
            return view;
        }
    }

    /**
     *
     ＊由于ViewPager 默认的切换速度有点快，因此用一个Scroller 来控制切换的速度
     * <p>而实际上ViewPager 切换本来就是用的Scroller来做的，因此我们可以通过反射来</p>
     * <p>获取取到ViewPager 的 mScroller 属性，然后替换成我们自己的Scroller</p>
     */
    public static class ViewPagerScroller extends Scroller {
        private int mDuration = 800;// ViewPager默认的最大Duration 为600,我们默认稍微大一点。值越大越慢。
        private boolean mIsUseDefaultDuration = false;

        public ViewPagerScroller(Context context) {
            super(context);
        }

        public ViewPagerScroller(Context context, Interpolator interpolator) {
            super(context, interpolator);
        }

        public ViewPagerScroller(Context context, Interpolator interpolator, boolean flywheel) {
            super(context, interpolator, flywheel);
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy) {
            super.startScroll(startX, startY, dx, dy,mDuration);
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy, int duration) {
            super.startScroll(startX, startY, dx, dy, mIsUseDefaultDuration?duration:mDuration);
        }

        public void setUseDefaultDuration(boolean useDefaultDuration) {
            mIsUseDefaultDuration = useDefaultDuration;
        }

        public boolean isUseDefaultDuration() {
            return mIsUseDefaultDuration;
        }

        public void setDuration(int duration) {
            mDuration = duration;
        }

        public int getScrollDuration() {
            return mDuration;
        }
    }

    public static int dpToPx(int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dp,
                Resources.getSystem().getDisplayMetrics());
    }
}
